﻿using System;
using System.Collections.Generic;
using System.Text;


using System.Net.Sockets;
using System.Net;
namespace SICOMModbus
{
    // <summary>  
    /// 异步“发送--接收”Socket类。作者：敖士伟 Email:ikmb@163.com  
    /// </summary>  
    public class SocketAsyncClient
    {
        //-------属性开始  
        /// <summary>  
        /// 发送/接收套节字  
        /// </summary>  
        private Socket SendSocket;

        /// <summary>  
        /// 网络端点( IP 地址和端口号)  
        /// </summary>  
        private IPEndPoint hostEndPoint;

        /// <summary>  
        /// 异步对象上下文  
        /// </summary>  
        //private SocketAsyncEventArgs SendEventArg;

        /// <summary>  
        /// 到回发消息委托  
        /// </summary>  
        /// <param name="msg">回发消息</param>  
        public delegate void ReceiveMSGHandler(Byte[] ReceiveBuffer);
        /// <summary>  
        /// 到回发消息事件  
        /// </summary>  
        public event ReceiveMSGHandler ReceiveMSGEvent;
        //-------属性结束  

        public delegate void SendErroHandler();
        public event SendErroHandler SendErroEvent;
        private bool connected;

        public bool Connected
        {
            get { return SendSocket.Connected; }
        }

        //public delegate void SendCompletedHandler();

        //public event SendCompletedHandler SendCompletedEvent;

        internal SocketAsyncClient(string ip, Int32 port)
        {
            this.hostEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            this.SendSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }

        public void connect()
        {
            try
            {
                this.SendSocket.Connect(hostEndPoint);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>  
        /// 发送消息  
        /// </summary>  
        /// <param name="msg">消息</param>  
        public void SendMsg(Byte[] sendBuffer)
        {
            //if (SendEventArg == null)
            //{
            SocketAsyncEventArgs SendEventArg = new SocketAsyncEventArgs();
            ////发送缓存  
            //Byte[] sendBuffer = Encoding.UTF8.GetBytes(msg);

            SendEventArg.SetBuffer(sendBuffer, 0, sendBuffer.Length);
            SendEventArg.UserToken = this.SendSocket;
            SendEventArg.RemoteEndPoint = this.hostEndPoint;
            //异步接收请求回调  
            SendEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
            //}
            //else
            //{
            //    //重用异步对象上下文时消除其socket  
            //    SendEventArg.AcceptSocket = null;
            //}


            //开始异步发送  
            Boolean willRaiseEvent = this.SendSocket.SendAsync(SendEventArg);

            //同步完成  
            if (!willRaiseEvent)
            {
                this.OnSendCompleted(null, SendEventArg);
            }
        }

        /// <summary>  
        /// 发送完成回调  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e">异步对象上下文</param>  
        private void OnSendCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {

                //SendCompletedEvent();

                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    // 准备接收  
                    Socket s = e.UserToken as Socket;
                    //接收缓存  
                    byte[] receiveBuffer = new byte[17];
                    e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                    //接收完成回调  
                    e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);
                    //开始异步接收  
                    Boolean willRaiseEvent = s.ReceiveAsync(e);
                    if (!willRaiseEvent)
                    {
                        this.OnReceiveCompleted(null, e);
                    }
                }
            }
            else
            {
                SendErroEvent();
                //this.CloseClientSocket(e);
            }
        }

        /// <summary>  
        /// 接收完成回调  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e">异步对象上下文</param>  
        private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
        {
            // 检查远程主机是否断开  
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                Socket s = e.UserToken as Socket;

                Int32 bytesTransferred = e.BytesTransferred;

                // Get the message received from the listener.  
                //String received = Encoding.UTF8.GetString(e.Buffer, e.Offset, bytesTransferred);

                //得到回发消息事件  
                ReceiveMSGEvent(e.Buffer);
            }
            else
            {
                Console.WriteLine("接收完成回调不成功 关闭Socket");
                this.CloseClientSocket(e);
            }
        }

        /// <summary>  
        /// 关闭socket  
        /// </summary>  
        /// <param name="e">异步对象上下文</param>  
        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;

            try
            {
                s.Shutdown(SocketShutdown.Send);
            }

            catch (Exception ex)
            {
                s.Close();
                //throw ex;
            }

        }

        internal void DisConnect()
        {
            try
            {
                //SendSocket.Shutdown(SocketShutdown.Send);

                SendSocket.Shutdown(SocketShutdown.Both);
                //线程延时3秒，使得sender关闭时间足够   
                System.Threading.Thread.Sleep(3000);
                SendSocket.Close();
                //线程延时3秒，使得this.client关闭时间足够   
                System.Threading.Thread.Sleep(3000);
            }
            catch (Exception ex)
            {
                SendSocket.Shutdown(SocketShutdown.Both);
                //线程延时3秒，使得sender关闭时间足够   
                System.Threading.Thread.Sleep(3000);
                SendSocket.Close();
                //线程延时3秒，使得this.client关闭时间足够   
                System.Threading.Thread.Sleep(3000);

                //throw ex;
            }
            //SendSocket.Close();
        }
    }
}
